/*
 *
 *  Created by John David Duncan on 2/20/09.
 *  Copyright 2009 Sun Microsystems. All rights reserved.
 *
 */

/*
 This program is free software; you can redistribute it and/or modify
 it under the terms of the GNU General Public License as published by
 the Free Software Foundation; version 2 of the License.
 
 This program is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 GNU General Public License for more details.
 
 You should have received a copy of the GNU General Public License
 along with this program; if not, write to the Free Software
 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA 
 */

#include <unistd.h>
#include <stdio.h>

#include <readline/readline.h>
#include <readline/history.h>

#include "Parser.h"

/* defines */
#define HISTFILE ".ddltool.history"
#define DUMP_BUFF 8192

/* typedefs */
typedef void Engine(Parser *, char *);

/* function prototypes */
void show_error(int);
// bool get_options(int&, char **&, OptionSpec *);
void usage();
void finish();
namespace Exec {
  void Run(Parser *, char *);
  void Dump(Parser *, char *);
  void TestParser(Parser *, char *);
};

/* statics -- file scope */
char * default_db = 0;
char * prior_schema = 0;
Engine *engines[3] = { Exec::Run , Exec::Dump , Exec::TestParser } ;
int action_id = EXE_RUN;

/* externs */
extern bool innobase_is_started;    // from SQLnode.cpp

/* implementations */


int main(int argc, char *argv[]) {
  Scanner *scanner;
  Parser *parser;
  char *cmdline;
  size_t cmd_len;
  Engine *run;
    
  /* ***  if(! get_options(argc, argv, options)) {
    usage();
    exit(1);
  }   *** */
  
  init_constants();
  ib_init();
  using_history();
  read_history(HISTFILE);
  
  cmdline = readline("> ");
  while(cmdline) {
    run = engines[action_id];
    cmd_len = strlen(cmdline);
    if(cmd_len) {
      add_history(cmdline);
      scanner = new Scanner((const unsigned char *) cmdline, cmd_len);
      parser = new Parser(scanner);

      try { parser->Parse(); }
      catch(quitException *q) { finish(); }
      
      run(parser, cmdline);    
    }
    cmdline = readline("> ");
  }
  
  finish();
}


void finish() {
  stifle_history(100);
  write_history(HISTFILE);
  printf("\n");
  
  if(innobase_is_started && isatty(STDIN_FILENO)) {
    int shutdown = - 1;
    while(shutdown == -1) {
      char *cmd = readline("Perform clean shutdown? [Y/n] ");
      if(cmd) {
        if(cmd[0] == 'Y' || cmd[0] == 'y' || cmd[0] == 0) shutdown = 1;
        else if(cmd[0] == 'N' || cmd[0] == 'n') shutdown = 0;
      }
    }
    if(shutdown) ib_shutdown();
  }

  exit(0);
}


void usage() {
  fprintf(stderr,"Hit em where they aint. \n");  
  exit(1);
}


void Exec::Run(Parser *parser, char *)  {       // Actually run the parse tree
  if(parser->errors->count) return;
  SQLnode *tree = parser->AST;
  if(tree) {
    int err = tree->Run();  
    if(err != DB_SUCCESS) show_error(err);
  }
} 


void  Exec::Dump(Parser *parser, char *) {       // Don't run the tree, just print it
  char buff[DUMP_BUFF];  
  char *p = buff; /* start */ 
  const char *s = buff + DUMP_BUFF; /* end */
  SQLnode *tree = parser->AST;
  
  if(parser->errors->count) return;    
  if(tree) tree->Dump(&p, s);
  puts(buff);
}


// Print the parse tree and the command line side-by-side
void  Exec::TestParser(Parser *parser, char *cmdline) {
  char buff[40], cmd[40];
  char *p = buff;  /* start */
  const char *s = buff + 40;  /* end */
  SQLnode *tree = parser->AST;
  
  if(parser->errors->count)    
    strcpy(p, "[INVALID PARSE TREE]");
  else if(tree) tree->Dump(&p, s);
  strncpy(cmd, cmdline, 39);
  buff[39] = cmd[39] = 0;
  printf("%-39s|%s\n", cmd, buff);
}


/* **
bool get_options(int &argc, char ** &argv, OptionSpec *options) {
  char c;
  
  while ((c = getopt(argc, argv, "c:d:h")) != -1) {
    switch(c) {
        
      case 'c':
        ;            break;
        
      case 'd':
        ;            break;
        
      case '?': case 'h': default:
        return false;    
    }
  }
  
  argc -= optind;
  argv += optind;
  
  return true;
}

*** */

